package com.hjy.backend.tableManager;


import com.hjy.common.error.Error;
import com.hjy.backend.utils.Panic;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

/**
 * 记录第一个表的 uid 于 .bt 文件中
 */
public class Starter {
    public static final String STARTER_SUFFIX = ".bt";
    public static final String STARTER_TMP_SUFFIX = ".bt_tmp";

    String path; // 文件地址
    File file;

    /**
     * 创建 .bt 文件
     *
     * @param path 文件路径
     * @return 一个新的 Starter 对象
     */
    public static Starter create(String path) {
        removeBadTmp(path);
        File f = new File(path + STARTER_SUFFIX);
        try {
            if (!f.createNewFile()) {
                Panic.panic(Error.FileExistsException);
            }
        } catch (Exception e) {
            Panic.panic(e);
        }
        if (!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }
        return new Starter(path, f);
    }

    /**
     * 加载曾经的 .bt 文件
     *
     * @param path 文件路径
     * @return 一个新的 Starter 对象
     */
    public static Starter open(String path) {
        removeBadTmp(path);
        File f = new File(path + STARTER_SUFFIX);
        if (!f.exists()) {
            Panic.panic(Error.FileNotExistsException);
        }
        if (!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }
        return new Starter(path, f);
    }

    /**
     * 删除临时 .bt_tmp文件
     *
     * @param path 文件路径
     */
    private static void removeBadTmp(String path) {
        new File(path + STARTER_TMP_SUFFIX).delete();
    }

    private Starter(String path, File file) {
        this.path = path;
        this.file = file;
    }

    /**
     * 加载 .bt 文件中的所有内容
     *
     * @return 文件内容二进制
     */
    public byte[] load() {
        byte[] buf = null;
        try {
            buf = Files.readAllBytes(file.toPath());
        } catch (IOException e) {
            Panic.panic(e);
        }
        return buf;
    }

    /**
     * 修改 .bt 文件内容
     * <p>
     * update 在修改 bt 文件内容时，没有直接对 bt 文件进行修改，而是首先将内容写入一个 bt_tmp 文件中，随后将这个文件重命名为 bt 文件。
     * <p>
     * 以期通过操作系统重命名文件的原子性，来保证操作的原子性
     *
     * @param data
     */
    public void update(byte[] data) {
        File tmp = new File(path + STARTER_TMP_SUFFIX);
        try {
            tmp.createNewFile();
        } catch (Exception e) {
            Panic.panic(e);
        }
        if (!tmp.canRead() || !tmp.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }
        try (FileOutputStream out = new FileOutputStream(tmp)) {
            out.write(data);
            out.flush();
        } catch (IOException e) {
            Panic.panic(e);
        }
        try {
            // 将文件内容复制到 .bt 文件中
            Files.move(tmp.toPath(), new File(path + STARTER_SUFFIX).toPath(), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            Panic.panic(e);
        }
        file = new File(path + STARTER_SUFFIX);
        if (!file.canRead() || !file.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }
    }

}
